package com.tanhua.server.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.tanhua.autoconfig.templates.AipFaceTemplate;
import com.tanhua.autoconfig.templates.HuanXinTemplate;
import com.tanhua.autoconfig.templates.OssTemplate;
import com.tanhua.autoconfig.templates.SmsTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.vo.UserInfoVo;
import com.tanhua.dubbo.api.db.UserApi;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.server.exceptions.TanhuaException;
import com.tanhua.server.interceptors.UserHolder;
import com.tanhua.server.utils.JwtUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserService {

    @Reference
    private UserApi userApi;
    @Reference
    private UserInfoApi userInfoApi;
    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private AipFaceTemplate aipFaceTemplate;
    @Autowired
    private OssTemplate ossTemplate;

    public ResponseEntity save(User user) {
        user.setCreated(new Date());
        user.setUpdated(new Date());
        String password = DigestUtils.md5Hex(user.getPassword());
        user.setPassword(password);  //密码加密
        Long userId = userApi.save(user);
        return ResponseEntity.ok(userId);
    }

    public ResponseEntity findByMobile(String mobile) {
        User user = userApi.findByMobile(mobile);
//        return ResponseEntity.ok(user);\
        return ResponseEntity.status(49494).body(user);
    }



//    发送验证码
    public ResponseEntity sendCode(String phone) throws Exception {
        String randomNumeric = "123456";
//        String randomNumeric = RandomStringUtils.randomNumeric(6);  //TODO 正式上线时需要放开
//        smsTemplate.sendSms(phone,randomNumeric); //发送短信验证码  //TODO 正式上线时需要放开
        System.out.println(randomNumeric);

        redisTemplate.boundValueOps("CODE_"+phone).set(randomNumeric,5, TimeUnit.MINUTES);

        return ResponseEntity.ok(null);
    }

    public ResponseEntity loginVerification(String phone, String verificationCode) {
//        1、从redis中获取验证码
        String randomNumeric = redisTemplate.boundValueOps("CODE_" + phone).get();
        if(StringUtils.isBlank(randomNumeric)){
//            告诉手机端验证码为空
            throw new TanhuaException(1234,"验证码失效");  //文案
        }
        if(!StringUtils.equals(randomNumeric,verificationCode)){
            throw new TanhuaException(1234,"验证码输入错误");  //文案
        }
        User user = userApi.findByMobile(phone);

        boolean isNew = false;
        if(user!=null){

        }else{
            isNew = true;
//            如果查不到用户，直接插入用户数据到tb_user表中
            user = new User();
//            user.setId();
            user.setMobile(phone);
            user.setPassword(DigestUtils.md5Hex("123456")); // 先随便给一个值
//            user.setCreated(new Date());
//            user.setUpdated(new Date());
            Long userId  = userApi.save(user);
            user.setId(userId);

//            把新用户注册到环信上
            huanXinTemplate.register(userId);

        }
        String token = JwtUtils.createToken(user.getMobile(), user.getId(), "class158");
//        需要把token存储起来  根据token判断当前登录人是谁
        redisTemplate.boundValueOps("TOKEN_"+token).set(JSON.toJSONString(user),2,TimeUnit.HOURS);
//        token 是通过jwt生成的
//        {"token":"","isNew":true}
        Map<String,Object> resultMap = new HashMap();
        resultMap.put("token",token);
        resultMap.put("isNew",isNew);


//        userId   logTime  type

        Map map = new HashMap();
        map.put("userId",user.getId());
        map.put("logTime", DateTime.now().toString("yyyy-MM-dd"));
        map.put("type",isNew?"0102":"0101");
        rocketMQTemplate.convertAndSend("log_type_topic",map);



        return ResponseEntity.ok(resultMap);

    }

    public ResponseEntity loginReginfo(UserInfo userInfo, String token) {
//        向tb_user_info表中插入数据

        User user = getUserByToken(token);

        userInfo.setId(user.getId());
//        userInfo.setCreated(new Date());
//        userInfo.setUpdated(new Date());
//        userInfo.setAge(); //  TODO 作业 自己计算年龄 不要自己写代码 百度去或者自己找工具类！！！

//        userInfo.getBirthday()
        int age = DateUtil.ageOfNow(userInfo.getBirthday());
        userInfo.setAge(age);
        userInfoApi.save(userInfo);

        return ResponseEntity.ok(null);
    }

    public User getUserByToken(String token) {
        String userStr = redisTemplate.boundValueOps("TOKEN_" + token).get();
        if(StringUtils.isBlank(userStr)){
            throw new TanhuaException(500,"token失效，请重新登录");
        }
//        把json字符串再转成user对象

//        再重新把用户信息放到redis中 两个小时
        redisTemplate.boundValueOps("TOKEN_" + token).set(userStr,2,TimeUnit.HOURS);

        return JSON.parseObject(userStr, User.class);
    }


    public ResponseEntity loginReginfoHead(MultipartFile headPhoto, String token) throws Exception {
//        1、判断是否为头像
        boolean detect = aipFaceTemplate.detect(headPhoto.getBytes());
        if(!detect){
            throw new TanhuaException(500,"请重新上传照片");
        }
//        2、上传到阿里云
        String avatar = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
//        3、更新用户的头像
//        update tb_user_info set avatar=? where id=?
        User user = getUserByToken(token);


        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setAvatar(avatar);
        userInfoApi.updateById(userInfo);

        return ResponseEntity.ok(null);


    }

    public ResponseEntity findById(Long id) {
       UserInfo userInfo =  userInfoApi.findById(id);

       UserInfoVo userInfoVo = new UserInfoVo();

//       是spring家的  copyProperties有要求：属性名和数据类型必须相等
        BeanUtils.copyProperties(userInfo,userInfoVo);
//        发现age不能被赋值 需要手动赋值
        if(userInfo.getAge()!=null){
            userInfoVo.setAge(userInfo.getAge().toString()); //会报空指针异常
        }

       return ResponseEntity.ok(userInfoVo);
    }

    public ResponseEntity updateUserInfo( UserInfo userInfo) {

        Long id = UserHolder.getUserId();
        userInfo.setId(id);
//        update tb_user_info set XXX=xx where id=?
//        userInfo.setUpdated(new Date());
        userInfoApi.updateById(userInfo);

        return ResponseEntity.ok(null);

    }
}
